package com.googlecode.openrtp.spi;

import java.util.concurrent.atomic.AtomicLong;

/**
 *
 * @author jocke
 */
public class SessionKeys {

    public static final Key<Long> RTP_PACKET_RATE = new KeyImpl("RTP_PACKET_RATE", Long.class);
    public static final Key<Long> RTP_PACKET_SIZE = new KeyImpl("RTP_PACKET_SIZE", Long.class);
    public static final Key<Long> AVG_SIZE_RTCP = new KeyImpl("AVG_SIZE_RTCP", Long.class);
    public static final Key<Long> TOTAL_SIZE_RTCP_PACKETS = new KeyImpl("TOTAL_SIZE_RTCP_PACKETS", Long.class);
    public static final Key<Long> LAST_SENT_RTCP_PACKAGE = new KeyImpl("LAST_SENT_RTCP_PACKAGE", Long.class);
    public static final Key<Long> NEXT_RTCP_TRANSMISSION = new KeyImpl("NEXT_RTCP_TRANSMISSION", Long.class);
    public static final Key<Long> NEXT_RTP_TRANSMISSION = new KeyImpl("NEXT_RTP_TRANSMISSION", Long.class);
    public static final Key<Long> TOTAL_RTP_PACKETS_IN_BYTES = new KeyImpl("TOTAL_RTP_PACKETS_IN_BYTES", Long.class);
    public static final Key<Long> LAST_ACTIVITY = new KeyImpl("LAST_ACTIVITY", Long.class);
    public static final Key<AtomicLong> TOTAL_NUMBER_RTCP_PACKETS = new KeyImpl("TOTAL_NUMBER_RTCP_PACKETS", AtomicLong.class);
    public static final Key<AtomicLong> TOTAL_NUMBER_RTP_PACKETS = new KeyImpl("TOTAL_NUMBER_RTP_PACKETS", AtomicLong.class);
    public static final Key<AtomicLong> SEQUNCE_NUMBER = new KeyImpl("SEQUNCE_NUMBER", AtomicLong.class);
    public static final Key<Boolean> HAS_SENT_RTP_SINCE_LAST_TWO_RTCP_PACKAGS  = new KeyImpl("HAS_SENT_RTP_SINCE_LAST_TWO_RTCP_PACKAGS", Boolean.class);
    public static final Key<Boolean> RTP_CONNECTED  = new KeyImpl("RTP_CONNECTED", Boolean.class);
    public static final Key<Boolean> RTCP_CONNECTED  = new KeyImpl("RTCP_CONNECTED", Boolean.class);
    public static final Key<Long> SSRC  = new KeyImpl("SSRC", Long.class);
    public static final Key<Long> AUDIO_SAMPLING_RATE  = new KeyImpl("AUDIO_SAMPLING_RATE", Long.class);
    public static final Key<PayloadType> PAYLOAD_TYPE  = new KeyImpl("PAYLOAD_TYPE", PayloadType.class);
    public static final Key<String> CNAME  = new KeyImpl("CNAME", String.class);

    public static class KeyImpl<T> implements Key<T> {

        private String name;
        
        private Class<T> type;
        
        private final int hash;

        public KeyImpl(String name, Class<T> type) {
            this.name = name;
            this.type = type;
            this.hash = calcHash();
        }

        @Override
        public String getKey() {
            return name;
        }

        @Override
        public Class<T> getType() {
            return type;
        }

        @Override
        public int hashCode() {
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final KeyImpl<T> other = (KeyImpl<T>) obj;
            return other.hash == hash;
        }

        private int calcHash() {
            int h = 7;
            h = 97 * h + (this.name != null ? this.name.hashCode() : 0);
            h = 97 * h + (this.type != null ? this.type.hashCode() : 0);
            return h;
        }
    }
}
